<?php

class Parser {
    
    /**
     * Parsed configuration file
     * @var str[]
     */
    var $config;
    
    /**
     * Database connection
     * @var resource
     */
    var $db;
    
    var $cube = array();
    
    /**
     * Constructor. Parses the configuration file "phprestsql.ini", grabs any 
     * request data sent, records the HTTP request method used and parses the 
     * request URL to find out the requested table name and primary key values.
     * @param str iniFile Configuration file to use
     */
    function Parser($iniFile = 'phprestsql.ini') {
        
        $this->config = parse_ini_file($iniFile, TRUE);
        $this->connect();
        
    }
    
    /**
     * Connect to the database.
     */
    function connect() {
        echo "Connect ...</br>";
        $database = $this->config['database']['type'];
        require_once($database.'.php');
        $this->db = new $database(); 
        if (isset($this->config['database']['username']) && isset($this->config['database']['password'])) {
            if (!$this->db->connect($this->config['database'])) {
                trigger_error('Could not connect to server', E_USER_ERROR);
            }
        } elseif (isset($_SERVER['PHP_AUTH_USER']) && isset($_SERVER['PHP_AUTH_PW'])) {
			$this->config['database']['username'] = $_SERVER['PHP_AUTH_USER'];
			$this->config['database']['password'] = $_SERVER['PHP_AUTH_PW'];
            if (!$this->db->connect($this->config['database'])) {
                exit;
            }
        } else {
            exit;
        }
        echo "Connect complete ...</br>";
    }
    
    /**
     * Execute the request.
     */
    function exec() {
   
        // Von der Forenliste suchen wir uns die Placer Foren raus ...
        // Das Forum "Logbücher" hat die Nummer 101, wir suchen erst alle Foren,
        // die als Elternforum die 101 haben. 
        // Für diese Foren suchen wir alle Foren, die diese als Eltern haben, 
        // das sind dann die Placer Foren.
        
        $placer_forums = $this->getForumsWithParent("101");
        
        $count = -1;
        
        foreach ($placer_forums as $forum) {
            
            $placerlist = $this->getForumsWithParent($forum["forum_id"]);
            
            foreach ($placerlist as $placer) {
                
                // Innerhalb der Placerforen suchen wir die Topics zu diesem
                // Forum. Da sollten nur die Letterboxen stehen
                $topiclist = $this->getTopicsForForum($placer["forum_id"]);
                
                // Der Letterbox-Zähler, wir fangen bei -1 an, damit wir am
                // Anfang der Schleife hochzählen können.
                
                // Nun laufen wir über alle Topics und bestimmen die Werte, die
                // von den Topics abhängen ...
                
                foreach ($topiclist as $topic) {
                    
                    // aber erst mal den Zähler erhöhen
                    
                    $count = $count + 1;
                    
                    // Topic-Id und Beitragsdatum können wir direkt abspeichern
                    
                    $this->addAttribute("topic", $topic["topic_id"], $count);
                    $this->addAttribute("placer_name", $topic["topic_first_poster_name"], $count);
                    
                    $datum = date("Y-m-d", $topic["topic_time"]);
                    $this->addAttribute("place_date", $datum, $count);
                    
                    // Letterbox-Name und PLZ können wir aus dem Topic bestimmen
                    
                    $tmp = preg_split("/-/", $topic["topic_title"], 0);
                    
                    $l = trim($tmp[0]);
                    
                    if (mb_strlen($l, "utf8") <= 3) {
                        $this->addAttribute("license_tag", $l, $count);
                        $this->addAttribute("name", trim($tmp[1]), $count);
                    } else {
                        $this->addAttribute("license_tag", "---", $count);
                        $this->addAttribute("name", trim($tmp[0]), $count);
                    }
                    
                    // Land und Bundesland und Placer 
                    
                    $tmp = $this->getMovedTopic($topic["topic_id"]); 
                    $tmp = $this->getForum($tmp["forum_id"]);
                    $forum_name = $tmp["forum_name"];
                    $this->addAttribute("province", $tmp["forum_name"], $count);
                    
                    $tmp = $this->getForum($tmp["parent_id"]);
                    $this->addAttribute("country", $tmp["forum_name"], $count);
                    
                    // Dann zu jedem dieser Topics den ersten Post, das ist der 
                    // zu parsende Text.
                    
                    $post = $this->getFirstPost($topic["topic_first_post_id"]);
                    
                    // Teile den Text in Zeilen und entferne Leerzeilen.

                    $lines = explode("\n", $post["post_text"]);
                    $lines = $this->removeEmptyLines($lines);
                    
                    // Das hier wollen wir alles finden:
                    
                    $coords         = null;
                    $length         = null;
                    $duration       = null;
                    $longitude      = "---";
                    $latitude       = "---";
                    $postal_code    = "---";
                    $city           = "---";
                    $puzzle         = "---";
                    $terrain        = "---";
                    $starting_point = "---";
                                        
                    foreach($lines as $line) {
                        
                        // Die bbcode tags sind in der Datenbank komischerweise
                        // mit einem Doppelpunkt und einer Nummer versehen.
                        // Das müssen wir erst mal entfernen
                        
                        $line = preg_replace("/(\[+.*?)(\:+.*?\])/", "$1]", $line);
                        
                        // Wir durchsuchen die Zeile nach coord= und map= ...
                        // Das sind unsere Nav-Koordinaten ...
                        
                        if (!isset($coords)) {
                            if (preg_match("/\[coord=(\d+\.?\d*),(\d+\.?\d*)\]/", $line, $tmp)) {
                                $longitude = $tmp[1];
                                $latitude = $tmp[2];
                                $coords = true;
                            }
                        }
                        if (!isset($coords)) {
                            if (preg_match("/\[maps=(\d+\.?\d*),(\d+\.?\d*)\]/", $line, $tmp)) {
                                $longitude = $tmp[1];
                                $latitude = $tmp[2];
                                $coords = true;
                            }
                        }
                        
                        // Nun entfernen wir die eckigen Klammern samt Inhalt ...
                        
                        $line = preg_replace("/\[+.*?\]+/", "", $line);
                        
                        // Wir splitten die Zeile bei ";" und nehmen nur den 
                        // ersten Teil ...
                        
                        $line = preg_split("/;/", $line)[0];
                        
                        // Nun splitten wir am ":" und teilen auf in key und 
                        // string
                        
                        $line = preg_split("/:/", $line, 0);
                        $key = trim($line[0]);
                        if (count($line) > 1) {
                            $line = trim($line[1]);
                        } else {
                            $line = null;
                        }
                        
                        // Die einzelnen Teile parsen ...
                        
                        switch ($key) {
                        case "Stadt":
                        case "Ort":
                            if (preg_match("/(\\d{5})(.*)/", $line, $tmp)) {
                                $postal_code = trim($tmp[1]);
                                $city = trim($tmp[2]);
                            }
                            if (preg_match("/\?\?\?/", $line, $tmp)) {
                                $city = "???";
                            }
                            break;
                        case "Startpunkt":
                            $starting_point = trim($line);
                            break;
                        case "Schwierigkeit":
                            preg_match("/\((.*)\)/U", $line, $tmp);
                            $puzzle = trim($tmp[1]);
                            break;   
                        case "Gelände":
                            preg_match("/\((.*)\)/U", $line, $tmp);
                            $terrain = trim($tmp[1]);
                            break;  
                        case "Länge":
                            $tmp   = $this->parseLength($line);
                            if (!isset($length)) {
                                $length = $tmp;
                            }
                            $tmp = $this->parseDuration($line);
                            if (!isset($duration)) {
                                $duration = $tmp;
                            }
                            break;
                        case "Dauer":
                            $tmp = $this->parseLength($line);
                            if (!isset($length)) {
                                $length = $tmp;
                            }
                            $tmp = $this->parseDuration($line);
                            if (!isset($duration)) {
                                $duration = $tmp;
                            }
                            break;                            
                        }

                    }
                    
                    // Prüfe, ob wir schon eine Länge gefunden haben. Wenn 
                    // nicht, setze die Länge auf "---".
                    
                    if (!isset($length)) {
                        $length = "---";
                    }
                    if (!isset($duration)) {
                        $duration = "---";
                    }
                    
                    // Hitchhiker und virtuelle Boxen kriegen bestimmte 
                    // Kennzeichen wieder "abgenommen"
                    
                    if ($forum_name == "Hitchhiker") {
                        $license_tag = "---";
                        $postal_code = "---";
                        $city = "---";
                        $puzzle = "---";
                        $terrain = "---";
                        $duration = "---";
                        $length = "---";                    
                    }    
                    
                    if ($forum_name == "Virtuelle Letterboxen") {
                        $license_tag = "---";
                        $postal_code = "---";
                        $city = "---";
                        $terrain = "---";
                        $duration = "---";
                        $length = "---";
                    }                       
                    
                    $this->addAttribute("duration", $duration, $count);
                    $this->addAttribute("length", $length, $count);
                    
                    $this->addAttribute("postal_code", $postal_code, $count);
                    $this->addAttribute("city", $city, $count);
                    $this->addAttribute("puzzle", $puzzle, $count);
                    $this->addAttribute("terrain", $terrain, $count);
                    $this->addAttribute("starting_point", $starting_point, $count);
                    $this->addAttribute("longitude", $longitude, $count);
                    $this->addAttribute("latitude", $latitude, $count);
                    
                } 
                
            }
        }    

        file_put_contents("/opt/lampp/htdocs/lbg_forum/lbg/scripts/lbg/boxes.json", json_encode($this->cube)); 
        
        $this->db->close();
        echo "Closed.</br>";
        
    }
    
    function addAttribute($attr, $value, $count) {
        
        if (!isset($this->cube[$attr])) {
            $this->cube[$attr] = array();
        }
       
        
        if (!isset($this->cube[$attr][$value])) {
            $this->cube[$attr][$value] = array();
        }
        
        $this->cube[$attr][$value][] = $count;

    }
    
    function removeEmptyLines($a) {
    
        $r = array_filter($a, function ($item) {
            return trim($item);
        });
        
        return $r;
        
    } 

    function parseDuration ($text) {
        if (preg_match("/(\d+)\s*(½)/i", $text, $tmp)) {
            return $tmp[1] + ",5";
        }     
        if (preg_match("/(\d+)\s*(1\/2)/i", $text, $tmp)) {
            return $tmp[1] + ",5";
        }        
        if (preg_match("/(\d+,?\d*)\s*?(st)/i", $text, $tmp)) {
            return $tmp[1];
        }
        if (preg_match("/(\d+,?\d*)\s*?(h\s)/i", $text, $tmp)) {
            return $tmp[1];
        }
        return null;
    }
    
    function parseLength ($text) {
        if (preg_match("/(\d+,?\d*)\s*?(km)/i", $text, $tmp)) {
            return $tmp[1];
        }
        return null;
    }    
    
    // Database functions
    
    function getForum($forum) {
        $filter = array();
        $filter['forum_id'] = $forum;
        $results = $this->db->get("phpbb_forums", $filter, null, null);
        return $results["rows"][0];
    }

    function getMovedTopic($topic) {
        $filter = array();
        $filter['topic_moved_id'] = $topic;
        $results = $this->db->get("phpbb_topics", $filter, null, null);
        return $results["rows"][0];
    }    
    
    
    function getForumsWithParent($parent) {
        $filter = array();
        $filter['parent_id'] = $parent;
        $results = $this->db->get("phpbb_forums", $filter, null, null);
        return $results["rows"];
    }
    
    function getTopicsForForum($forum) {
        $filter = array();
        $filter['forum_id'] = $forum;
        $results = $this->db->get("phpbb_topics", $filter, null, null);
        return $results["rows"];
    }  
    
    function getFirstPost($post) {
        $filter = array();
        $filter["post_id"] = $post;
        $results = $this->db->get("phpbb_posts", $filter, null, null);
        return $results["rows"][0];
    }       
    
}

?>
